package com.hapzxb.thread.future2callback;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @author ddd
 * @date 2022-12-03 14:29
 *
 * Future
 * 参数类型 V - 未来的 get方法返回的结果类型 All Known Subinterfaces: Response <T>， RunnableFuture <V>，
 * RunnableScheduledFuture <V>， ScheduledFuture < 所有已知实现类： CompletableFuture ， CountedCompleter ， ForkJoinTask ，
 * FutureTask ， RecursiveAction ， RecursiveTask ， SwingWorker
 * <p>
 * public interface Future<V> A Future计算的结果。 提供方法来检查计算是否完成，等待其完成，并检索计算结果。 结果只能在计算完成后使用方法get进行检索，如有必要，阻塞，直到准备就绪。
 * 取消由cancel方法执行。 提供其他方法来确定任务是否正常完成或被取消。 计算完成后，不能取消计算。 如果您想使用Future
 * ，以便不可撤销，但不提供可用的结果，则可以声明Future<?>表格的类型，并返回null作为基础任务的结果。
 *
 *
 * FutureTask
 *
 * java.util.concurrent
 * Class FutureTask<V>
 * java.lang.Object
 * java.util.concurrent.FutureTask<V>
 * 参数类型
 * V - 此FutureTask的 get方法返回的结果类型
 * All Implemented Interfaces:
 *  Runnable ， Future <V>， RunnableFuture <V>
 *
 * public class FutureTask<V>
 * extends Object
 * implements RunnableFuture<V>
 * 可取消的异步计算。 该类提供了一个Future的基本实现 ，具有启动和取消计算的方法，查询计算是否完整，并检索计算结果。 结果只能在计算完成后才能检索; 如果计算尚未完成，则get方法将阻止。 一旦计算完成，则无法重新启动或取消计算（除非使用runAndReset()调用计算 ）。
 * A FutureTask可用于包装Callable或Runnable对象。 因为FutureTask实现Runnable ，一个FutureTask可以提交到一个Executor执行。
 *
 * 除了作为独立类之外，此类还提供了protected功能，在创建自定义任务类时可能很有用。
 */
public class FutureTaskDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        FutureTask<String> futureTask = new FutureTask<>(() -> {
            System.out.println("-----come in FutureTask");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "" + ThreadLocalRandom.current().nextInt(100);
        });

        Thread t1 = new Thread(futureTask, "t1");
        t1.start();

        //3秒钟后才出来结果，还没有计算你提前来拿(只要一调用get方法，对于结果就是不见不散，会导致阻塞)
        System.out.println(Thread.currentThread().getName()+"\t"+futureTask.get());

        //3秒钟后才出来结果，我只想等待1秒钟，过时不候
//        System.out.println(Thread.currentThread().getName() + "\t" + futureTask.get(1L, TimeUnit.SECONDS));

        System.out.println(Thread.currentThread().getName() + "\t" + " run... here");
    }
}
